﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Collections.Generic;

namespace Kaskelot.SP.UI.Analys.Data.Mapping
{
    public static class Mapper
    {
        #region ServiceModel to ViewModel
        
        public static ViewModel.Entity ToEntityViewModel(this AnalyseService.Entity entity, bool isChecked)
        {
            ViewModel.Entity result = new ViewModel.Entity
            {
                Name = entity.Name,
                Fields = entity.Fields.Select(f => f.ToFieldViewModel()).ToList(),
                CannotBeCombinedWith = entity.CannotBeCombinedWith != null ? entity.CannotBeCombinedWith.ToList() : new List<string>(),
                Checked = entity.IsChecked,
                IsEnabled = true,
                IsPrimary = entity.IsPrimary
            };

            return result;
        }

        public static ViewModel.Field ToFieldViewModel(this AnalyseService.Field field)
        {
            var viewField = new ViewModel.Field
            {
                NameInGrid = field.NameInGrid,
                NameInQueryBuilder = field.NameInQueryBuilder,
                InternalName = field.InternalName,
                DataType = Type.GetType(field.DataType),
                DataTypeInGrid = Type.GetType(field.DataTypeInGrid),
                LookupColumn = field.LookupColumn,
                Checked = field.IsChecked
            };
            return viewField;
        }

        public static ViewModel.IFilterPart ToFilterViewModel(object filter)
        {
            ViewModel.IFilterPart part = null;
            if (filter is AnalyseService.FieldFilter)
            {
                AnalyseService.FieldFilter ff = filter as AnalyseService.FieldFilter;
                part = new ViewModel.FieldFilter
                {
                    Field = ff.Field.ToFieldViewModel(),
                    Operator = (ViewModel.FilterOperator)ff.Operator,
                    Value = ff.Value
                };
            }
            else if (filter is AnalyseService.FilterGroup)
            {
                AnalyseService.FilterGroup fg = filter as AnalyseService.FilterGroup;
                part = new ViewModel.FilterGroup
                {
                    Operator = (ViewModel.GroupOperator)fg.Operator,
                    Parts = fg.Parts.Select(p => ToFilterViewModel(p)).ToList()
                };
            }

            return part;
        }

        public static ViewModel.QueryResult ToQueryResultViewModel(this AnalyseService.QueryResult result)
        {
            ViewModel.QueryResult vmResult = new ViewModel.QueryResult();

            vmResult.Data = result.Data;
            vmResult.ErrorMessage = result.ErrorMessage;
            vmResult.HasError = result.HasError;

            return vmResult;
        }

        public static ViewModel.LookupField ToLookupFieldViewModel(this AnalyseService.LookupField field)
        {
            return new ViewModel.LookupField
            {
                FieldName = field.FieldName,
                Values = field.Values.Select(v => new ViewModel.LookupValue
                {
                    ID = v.ID,
                    Value = v.Value
                }).ToList()
            };
        }

        public static ViewModel.Query ToQueryViewModel(this AnalyseService.Query query)
        {
            return new ViewModel.Query
            {
                ID = query.QueryID,
                Name = query.Name,
                //DisplayFields = query.DisplayFields.Select(d => d.ToFieldViewModel()).ToList(),
                Entities = query.Entities.Select(e => e.ToEntityViewModel(true)).ToList(),
                Filters = query.Filters.Select(f => ToFilterViewModel(f)).ToList(),
                IsPersonal = query.IsPersonal
            };
        }

        #endregion

        #region ViewModel to ServiceModel

        public static AnalyseService.Query ToQueryServiceModel(this ViewModel.Query query)
        {
            var serviceModel = new AnalyseService.Query();
            serviceModel.Name = query.Name;
            serviceModel.DisplayFields = new ObservableCollection<AnalyseService.Field>();
            serviceModel.IsPersonal = query.IsPersonal;
            serviceModel.QueryID = query.ID;
            query.DisplayFields.ForEach((ViewModel.Field f) =>
                {
                    serviceModel.DisplayFields.Add(f.ToFieldServiceModel());
                });

            serviceModel.Filters = new ObservableCollection<AnalyseService.IFilterPart>();
            query.Filters.ForEach((ViewModel.IFilterPart part) =>
                {
                    serviceModel.Filters.Add(part.ToFilterServiceModel());
                });

            serviceModel.Entities = new ObservableCollection<AnalyseService.Entity>();
            query.Entities.ToList().ForEach((ViewModel.Entity entity) =>
                {
                    serviceModel.Entities.Add(entity.ToEntityServiceModel());
                });


            return serviceModel;
        }

        public static AnalyseService.Entity ToEntityServiceModel(this ViewModel.Entity entity)
        {
            AnalyseService.Entity e = new AnalyseService.Entity
            {
                Name = entity.Name,
                IsChecked = entity.Checked,
                IsPrimary = entity.IsPrimary
            };

            e.Fields = new ObservableCollection<AnalyseService.Field>();
            entity.Fields.ForEach(delegate(ViewModel.Field field)
            {
                e.Fields.Add(field.ToFieldServiceModel());
            });

            e.CannotBeCombinedWith = new ObservableCollection<string>();
            entity.CannotBeCombinedWith.ForEach(delegate(string field)
            {
                e.CannotBeCombinedWith.Add(field);
            });

            return e;
        }

        public static AnalyseService.Field ToFieldServiceModel(this ViewModel.Field field)
        {
            return new AnalyseService.Field
                    {
                        DataType = field.DataType.ToString(),
                        DataTypeInGrid = field.DataTypeInGrid.ToString(),
                        InternalName = field.InternalName,
                        NameInGrid = field.NameInGrid,
                        NameInQueryBuilder = field.NameInQueryBuilder,
                        LookupColumn = field.LookupColumn,
                        IsChecked = field.Checked
                    };
        }

        public static AnalyseService.IFilterPart ToFilterServiceModel(this ViewModel.IFilterPart filterpart)
        {
            if (filterpart is ViewModel.FieldFilter)
            {
                var fieldFilter = filterpart as ViewModel.FieldFilter;
                return new AnalyseService.FieldFilter
                {
                    Field = fieldFilter.Field.ToFieldServiceModel(),
                    Operator = (AnalyseService.FilterOperator)fieldFilter.Operator,
                    Value = fieldFilter.Value
                };
            }
            else
            {
                var group = filterpart as ViewModel.FilterGroup;
                var parts = new ObservableCollection<AnalyseService.IFilterPart>();
                group.Parts.ForEach((ViewModel.IFilterPart part) =>
                    {
                        parts.Add(part.ToFilterServiceModel());
                    });

                return new AnalyseService.FilterGroup
                {
                    Operator = group.Operator == ViewModel.GroupOperator.And ? AnalyseService.GroupOperator.And : AnalyseService.GroupOperator.Or,
                    Parts = parts
                };
            }
        }

        #endregion
    }
}
